package P140_UseGuavaUtilsPackage;

import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Table;
import com.google.common.primitives.Ints;
import jdk.nashorn.internal.ir.annotations.Immutable;
import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

/**
 * Desc:&emsp;&ensp;推荐使用Guava工具包
 * 说起Guava （ 石榴） ， 可能知道它的读者并不多， 要是说起Google-collections ， 相信大
 * 部分读者都有所耳闻。2008 年Google 发布了Google-collections 扩展工具包， 主要是对JDK
 * 的Collection 包进行了扩展， 2010 年Google 发布了Guava 项目， 其中包含了collections 、
 * caching 、pnmitives support 、concurrency libraries 、common annotations 、I/O 等， 这些都是
 * 项目编码中的基本工具包， 我们大致浏览一下它的主要功能。
 *
 * @author 李渊&emsp;liyuan7@yusys.com.cn
 * @version 1.0
 * @since V4.3&emsp;2022/5/20
 */
public class UseGuavaUtilsPackage {


    /**
     * （一）CoIIections
     * com.google.common.collect 包中主要包括四部分： 不可变集合（ lmmutable Collections ） 、
     * 多值Map 、Table 表和集合工具类。
     */
    /* 1.不可变集合
    不可变集合包括ImmutableList 、ImmutableMap 、ImmutableSet 、ImmutabIeSortedMap 、
    ImmutableS ortedSet 等， 它比不可修改集合(Unmodifiable Collections) 更容易使用， 效率更
    高， 而且占用的内存更少。示例代码如下：
    */
    // A.不可变列表
    ImmutableList<String> list = ImmutableList.of("A","B","C");
    //B.不可变Map
    ImmutableMap<Integer, String> map = ImmutableMap.of(1, "A", 2, "B", 3, "C");
    // 其中的of 方法有多个重载， 其目的就是为了便于在初始化的时候直接生成一个不可变集合

    /* 2.多值Map
     多值Map 比较简单， 在JDK 中， Map 中的一个键对应一个值， 在put 一个键值对时，
     如果键重复了， 则会覆盖原有的值， 在大多数情况下这比较符合实际应用， 但有的时候确实
     会存在一个键对应多个值的情况， 比如我们的通讯录， 一个人可能会对应两个或三个号码，
     比时使用JDK 的Map 就有点麻烦了。在这种情况下， 使用Guava 的Multimap 可以很好地解
     夹问题， 代码如下：
     */
    public static void main(String[] args) {
        Multimap<String,String> phoneBook = ArrayListMultimap.create();
        phoneBook.put("张三","110");
        phoneBook.put("张三","119");
        // 输出一个collection[110, 119]
        System.out.println(phoneBook.get("张三"));
    }
    /* 3.table表
     在GIS （ Geographic lnformation System ， 地理信息系统） 中， 我们经常会把一个地点标
    注在一个坐标上， 比如把上海人民广场标注在北纬3L23 、东经121.48 的位置上， 也就是说
    只要给出了准确的经度和纬度就可以进行精确的定位一一一两个键决定一个值， 这在Guava 中
    使用Table来表示的
     */
    @Test
    public void testTable(){
        Table<Double,Double,String> g = HashBasedTable.create();
        g.put(31.23, 121.48, "人民广场");
        System.out.println(g.get(31.23, 121.48));
    }

    /* 4.集合工具类
     Guava 的集合工具类分得比较细， 比如Lists 、Maps 、Sets 分别对应的是List 、Map 、
    Set 的工具类， 它们的使用方法比较简单， 比如Map 的过滤， 如下所示。
     */
    @Test
    public void testColUtils(){
        Map<String,Integer> user  = new HashMap<>();
        user.put("A",20);
        user.put("B",20);
        user.put("C",20);
        Map<String, Integer> filterMap = Maps.filterValues(user, _age -> _age>20);
    }
    /**
     * （二）字符串操作
     * Guava 提供了两个非常好用的字符串操作工具： Joiner 连接器和splitter 拆分器。当然，
     * 字符串的连接和拆分使用JDK 的方法也可以实现， 但是使用Guava 更简单一些， 比如字符
     * 串的连接， 代码如下所示：
     */
    @Test
    public void testStringUtils() {
        Joiner joiner = Joiner.on(", ");
        String str = joiner.skipNulls().join("A",null,"B");
        Map<String,String> map = new HashMap<>();
        map.put("A","B");
        map.put("C","D");
        System.out.println(Joiner.on("\r\n").withKeyValueSeparator(" 和 ").join(map));
        //Joiner 不仅能够连接字符串， 还能够把Map 中的键值对串联起来， 比直接输出Map 优
        //雅了许多。Splitter 是做字符拆分的， 使用方法也比较简单， 示例代码如下：
        String str2 = "你好世界，hello world";
        // 以中文逗号分隔
        for (String s:Splitter.on("，").split(str2)){
            System.out.println(s);
        }
        // 按照固定长度分割
        for (String s:Splitter.fixedLength(2).split(str2)){
            System.out.println(s);
        }
    }

    /**
     * （三）基本类型工具
     * 基本类型工具在primitives 包中， 是以基本类型名+s 的方式命名的， 比如lnts 是int 的
     * 工具类， Doubles 是double 的工具类， 注意这些都是针对基本类型的， 而不是针对包装类型
     * 的。如下代码所示
     */
    @Test
    public void testBaseTypeUtils() {
        int[] ints = { 10, 9, 20, 40, 80};
        // 从数组中取出最大值
        System.out.println(Ints.max(ints));
        List<Integer> integers = new ArrayList<>();
        ints = Ints.toArray(integers);
    }
}
